# -*- coding: utf-8 -*-
import random
import subprocess
import time
import logging
import argparse

from appium import webdriver
# from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException, TimeoutException

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logger = logging

APP = "XHS"

app_package_map = {
    "XHS": ("com.xingin.xhs", ".index.v2.IndexActivityV2")
}


class XHSAppiumOperate:
    def __init__(self, **kwargs):
        self.screen_width = None
        self.screen_height = None

        self.idea = kwargs.get("idea")
        self.text = kwargs.get("text")
        self.content = kwargs.get("content")
        self.deviceName = kwargs.get("deviceName")
        self.appium_url = kwargs.get("appium_url")
        self.platformVersion = kwargs.get("platformVersion")
        self.systemPort = kwargs.get("systemPort")
        self.adbPort = kwargs.get("adbPort")
        self.template = kwargs.get("template", "基础")
        self.job_id = kwargs.get("job_id")

        self.driver = None
        self.max_retries = 3
        self.failure_count = 0
        self.view_count = 0
        self.like_count = 0
        self.comment_count = 0
        self.follow_count = 0

    def run(self):
        while self.max_retries > 0:
            try:
                if self.driver:
                    self.driver.quit()
                self.connection()
                logger.info(f"设备 {self.deviceName} 连接成功")
                time.sleep(3)

                logger.info("开始执行小红书发文字任务...")
                self.script()

                break
            except Exception as e:
                logger.error(f"发生异常: {e}")
                self.failure_count += 1
                self.max_retries -= 1
                if self.max_retries == 0:
                    self.normal_end()
                    raise Exception("任务失败")
        logger.info("任务结束")

    @staticmethod
    def execute_adb_command(adb_command):
        """
        执行单条 ADB 命令

        :param adb_command: 完整的 ADB 命令字符串
        :return: 命令执行结果（stdout）
        """
        try:
            logger.info(f"执行 ADB 命令: {adb_command}")
            result = subprocess.run(
                adb_command,
                shell=True,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            logger.info(f"命令执行成功: {adb_command}")
            return result.stdout.decode('utf-8')
        except subprocess.CalledProcessError as e:
            logger.error(f"命令执行失败: {adb_command}")
            logger.error(f"错误信息: {e.stderr.decode('utf-8')}")

    def initialize_device_settings(self):
        """
        执行设备初始化所需的 ADB 命令
        """
        logger.info("开始初始化设备设置")

        commands = [
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global adb_keep_usb_enabled 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global miui_optimization 0",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global tcp_keepalive 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell dumpsys battery unplug",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global background_process_limit 5",
            f"adb -s {self.deviceName} -P {self.adbPort} shell am set-standby-bucket io.appium.uiautomator2.server ACTIVE",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm trim-caches 500M",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell input keyevent KEYCODE_CLEAR"
        ]

        for cmd in commands:
            try:
                self.execute_adb_command(cmd)
            except Exception as e:
                logger.error(f"执行命令失败: {cmd}")
                logger.error(f"错误详情: {e}")

    def connection(self):
        self.initialize_device_settings()
        desired_caps = {
            "platformName": "Android",
            "platformVersion": self.platformVersion,
            "deviceName": self.deviceName,
            "udid": self.deviceName,
            "automationName": "UiAutomator2",
            "appPackage": app_package_map[APP][0],
            "appActivity": app_package_map[APP][1],
            "noReset": True,
            "fullReset": False,
            "systemPort": int(self.systemPort),
            "adbPort": int(self.adbPort),
            "appWaitForLaunch": True,
            "noSign": True,
            "autoLaunch": True,
            "newCommandTimeout": 180,
            "skipLogcatCapture": True,
            "disableWindowAnimation": True,
            "disableAndroidWatchers": True,
            "adbExecTimeout": 30000,
            "uiautomator2ServerInstallTimeout": 60000,
            "skipDeviceInitialization": True,
        }

        # self.driver = webdriver.Remote(self.appium_url, options=UiAutomator2Options().load_capabilities(desired_caps))
        self.driver = webdriver.Remote(self.appium_url, desired_caps)
        self.screen_width, self.screen_height = self.get_window_size()

    def script(self):
        """
        主流程：执行小红书文字发布的完整自动化流程
        包括：
            - 打开发布页面
            - 选择“写文字”
            -选择模板并下一步
            - 填写标题与正文
            - 提交发布
        """

        logger.info("开始执行【发布图文】任务")

        # 步骤 1: 打开“发布”页面（点击首页底部的发布按钮）
        self._open_publish_page()

        # 步骤 2: 点击“写文字”
        self._select_album()

        # 步骤 3: 写想法,bing
        self._fill_content()
        # 步骤 5: 选择模板并下一步
        self._choose_template()
        # 步骤 6: 填写标题和正文内容
        self._fill_title_and_content()

        # 步骤 7: 最终发布笔记并等待上传完成
        self._submit_post()

        logger.info("【发布图文】任务完成")

        # 返回首页并退出 Appium 会话

        self.normal_end()

    def _open_publish_page(self):
        logger.info("正在打开【发布】页面")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.RelativeLayout[@content-desc="发布"]',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

    def _select_album(self):
        logger.info("点击【写文字】")
        element = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().text("写文字")',
            timeout=5
        )
        element.click()
        time.sleep(random.uniform(2, 3))

    def _fill_content(self):
        logger.info("开始填写想法")

        logger.debug("点击写想法")
        title_input = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().resourceId("com.xingin.xhs:id/0_resource_name_obfuscated").instance(5)',
            timeout=5
        )
        title_input.click()
        time.sleep(2)
        # 重新定位点击后出现的 EditText
        edit_text = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.EditText[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated"]',
            timeout=5
        )

        edit_text.send_keys(self.idea)
        logger.info("想法已填写")
        logger.info("进入下一步")
        next_btn = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().textContains("下一步")',
            timeout=8
        )
        next_btn.click()
        time.sleep(random.uniform(8, 10))

    def _choose_template(self):
        logger.info("开始选择模板")
        max_swipes = 7  # 最大滑动次数
        swipe_count = 0

        # 使用参数化的模板名称
        logger.info(f"准备选择【{self.template}】模板")

        while swipe_count <= max_swipes:
            try:
                # 1. 定位目标模板的文本元素并点击
                template_text = self.find_element_with_retry(
                    by=AppiumBy.ANDROID_UIAUTOMATOR,
                    value=f'new UiSelector().text("{self.template}")',
                    timeout=5
                )
                template_text.click()
                logger.info(f"已点击【{self.template}】模板文本，完成选择")
                time.sleep(random.uniform(1, 2))

                # 2. 点击下一步按钮
                next_btn = self.find_element_with_retry(
                    by=AppiumBy.ANDROID_UIAUTOMATOR,
                    value='new UiSelector().textContains("下一步")',
                    timeout=5
                )
                next_btn.click()
                logger.info("模板选择完成，已进入下一步")
                time.sleep(random.uniform(8, 10))
                return  # 成功找到模板，退出方法

            except NoSuchElementException:
                if swipe_count < max_swipes:
                    logger.info(f"未找到【{self.template}】模板，尝试横向滑动 ({swipe_count + 1}/{max_swipes})")
                    self.horizontal_swipe_template_container()
                    swipe_count += 1
                    time.sleep(1)  # 等待滑动完成
                else:
                    raise NoSuchElementException(f"滑动{max_swipes}次后仍未找到【{self.template}】模板")

            except Exception as e:
                logger.error(f"选择模板过程中发生错误: {e}")
                raise

    def horizontal_swipe_template_container(self):
        """横向滑动模板选择容器"""
        try:
            # 定位RecyclerView容器（根据你提供的结构）
            recycler_view = self.find_element_with_retry(
                by=AppiumBy.ANDROID_UIAUTOMATOR,
                value='new UiSelector().className("androidx.recyclerview.widget.RecyclerView")',
                timeout=5
            )

            # 获取容器位置和尺寸
            location = recycler_view.location
            size = recycler_view.size

            # 计算滑动起点和终点（从右向左滑动）
            start_x = location['x'] + size['width'] * 0.8  # 右侧80%位置
            end_x = location['x'] + size['width'] * 0.2  # 左侧20%位置
            y = location['y'] + size['height'] * 0.5  # 垂直居中

            # 执行滑动（持续400ms，模拟人类操作）
            self.driver.swipe(start_x, y, end_x, y, 400)
            logger.info("已执行横向滑动")

        except Exception as e:
            logger.error(f"滑动模板容器失败: {e}")
            # 滑动失败时仍继续执行，不中断流程

    def _fill_title_and_content(self):
        logger.info("开始填写标题和正文内容")

        logger.debug("点击标题输入框")
        title_input = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().textContains("标题")',
            timeout=5
        )
        title_input.click()
        time.sleep(2)
        title_input.send_keys(self.text)
        logger.info("标题内容已填写")

        logger.debug("点击正文输入框")
        content_group = self.find_element_with_retry(
            by=AppiumBy.ANDROID_UIAUTOMATOR,
            value='new UiSelector().className("android.view.ViewGroup").instance(2)',
            timeout=5
        )
        content_input = content_group.find_element(AppiumBy.XPATH, '//android.widget.EditText')

        content_input.click()
        time.sleep(1)
        self.send_keys_with_newline(content_input, self.content)
        logger.info("正文内容已填写")

    def set_clipboard_content(self, text):
        self.driver.set_clipboard_text(text)
        logger.info(f"剪贴板内容已设置为: {text}")

    def send_keys_with_newline(self, element, text):
        logger.info("正在输入内容：" + text)
        text = text.replace("\\n", "\n")

        if '#' in text:
            # 以第一个 '#' 分割字符串
            parts = text.split('#', 1)
            before_hash = parts[0]
            after_hash = '#' + parts[1]  # 保留 # 和后面的部分

            # 发送 # 前的内容
            if before_hash:
                element.send_keys(before_hash)
                time.sleep(1)

            # 逐个字符复制粘贴 # 及之后的内容
            for i, char in enumerate(after_hash):
                # 设置剪贴板内容为当前字符
                self.set_clipboard_content(char)
                time.sleep(2)  # 稍作延迟确保设置成功

                # 模拟粘贴操作
                # if i == 0:
                #     element.click()
                self.driver.press_keycode(50, 28672)  # 使用粘贴快捷键
                # KEYCODE PASTE = 50
                time.sleep(2)  # 稍作延迟确保粘贴成功
        else:
            # 如果没有 #，直接发送全部内容
            element.send_keys(text)

    def _submit_post(self):
        logger.info("准备提交内容")
        publish_button = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.Button[@resource-id="com.xingin.xhs:id/0_resource_name_obfuscated" and @text="发布"]',
            timeout=5
        )
        publish_button.click()
        logger.info("内容已提交，等待发布结果")
        time.sleep(20)  # 视网络情况可调整

    def find_element_with_retry(self, by, value, timeout=5):
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((by, value))
            )
            return element
        except TimeoutException:
            raise NoSuchElementException(f"找不到元素: {value}")

    def get_window_size(self):
        size = self.driver.get_window_size()
        return size['width'], size['height']

    def normal_end(self):
        logger.info("返回首页并退出")
        self.driver.press_keycode(3)  # HOME 键
        self.driver.quit()


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-j', '--job_id', dest='job_id', type=str, default=None, required=True, help='target job_id')
    parser.add_argument('-u', '--appium_url', dest='appium_url', type=str, default=None, help='target appium_url')
    parser.add_argument('-d', '--deviceName', dest='deviceName', type=str, default=None, help='target deviceName')
    parser.add_argument('-s', '--systemPort', dest='systemPort', type=str, default=None, help='target systemPort')
    parser.add_argument('-a', '--adbPort', dest='adbPort', type=str, default=None, help='target adbPort')
    parser.add_argument('-p', '--platformName', dest='platformName', type=str, default=None, help='target platformName')
    parser.add_argument('-ver', '--platformVersion', dest='platformVersion', type=str, default=None,
                        help='target platformVersion')
    parser.add_argument('-accountId', '--accountId', dest='accountId', type=str, default="000", help='target accountId')

    parser.add_argument('-v', '--variables', dest='variables', type=str, default='{}', help='target variables')
    parser.add_argument('-template', '--template', type=str, default="基础")  # 新增这一行
    parser.add_argument('-text', '--text', type=str, required=True)
    parser.add_argument('-idea', '--idea', type=str, required=True)
    parser.add_argument('-content', '--content', type=str, required=True)

    args = parser.parse_args()
    XHSAppiumOperate(**vars(args)).run()
